home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / bmdist.arc / SEND.C < prev    next >
C/C++ Source or Header  |  1988-10-13  |  12KB  |  529 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <time.h>
  4. #include <ctype.h>
  5. #if    (defined(UNIX) || defined(MICROSOFT))
  6. #include <sys/types.h>
  7. #endif
  8. #include "bm.h"
  9.  
  10. struct addr *addrecip();
  11. char *ptime();
  12.  
  13. /* send a message */
  14. dosmtpsend(mfp,toargs,nargs,subject)
  15. FILE *mfp;
  16. char *toargs[];
  17. int nargs;
  18. char *subject;
  19. {
  20.     char    smtp_subject[LINELEN], 
  21.         tstring[LINELEN];
  22.     char    *tmpnam();
  23.     FILE     *fpin;
  24.     char    *p;
  25.     char     *tf = "bmXXXXXX";        /* temp file name */
  26.     int    c;
  27.     int    n;
  28.     long    sequence;
  29.     struct    addr *tolist,*tp;
  30.     register FILE    *tfile;
  31.     time_t    t;
  32.  
  33.  
  34.     if (nargs == 0) {
  35.         printf("No recpients\n");
  36.         return 0;
  37.     }
  38.     fpin = mfp;
  39.     if ((tolist = make_tolist(nargs,toargs)) == NULLADDR) {
  40.         printf("Send aborted\n");
  41.         return 0;
  42.     }
  43.  
  44.     sequence = get_msgid();
  45.  
  46.     time(&t);
  47.     mktemp(tf);
  48.         /* open textfile for write */
  49.     if ((tfile = fopen(tf,"w+")) == NULLFILE) {
  50.         perror(tf);
  51.         del_addrlist(tolist);
  52.         return 1;
  53.     }
  54.  
  55.     if (!qflag) {
  56.         /* write RFC822-compatible headers using above information */
  57.         fprintf(tfile,"Date: %s",ptime(&t));
  58.         fprintf(tfile,"Message-Id: <%ld@%s>\n",sequence,hostname);
  59.         fprintf(tfile,"From: %s@%s",username,hostname);
  60.         if (fullname != NULLCHAR && *fullname != '\0')
  61.             fprintf(tfile," (%s)",fullname);
  62.         fprintf(tfile,"\n");
  63.         if (replyto != NULLCHAR && *replyto != '\0')
  64.             fprintf(tfile,"Reply-To: %s\n",replyto);
  65.         strcpy(tstring,"To: ");
  66.         for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  67.             strcat(tstring,tp->user);
  68.             if (tp->host != NULLCHAR || *tp->host != '\0') {
  69.                 strcat(tstring,"@");
  70.                 strcat(tstring,tp->host);
  71.             }
  72.             n = strlen(tstring);
  73.             if (tp->next) {
  74.                 if (n > 50) {
  75.                     fprintf(tfile,"%s,\n\t",tstring);
  76.                     if (tty) printf("%s,\n ",tstring);
  77.                     *tstring = '\0';
  78.                 } else
  79.                     strcat(tstring,", ");
  80.             }
  81.         }
  82.         fprintf(tfile,"%s\n",tstring);
  83.         if (tty) printf("%s\n",tstring); 
  84.  
  85.         *smtp_subject = '\0';
  86.         if (subject == NULL && tty) {
  87.             /* prompt and get Subject: */
  88.             printf("Subject: ");
  89.             gets(smtp_subject);
  90.         } else {
  91.             strcpy(smtp_subject,subject);
  92.             if(tty) printf("Subject: %s\n",smtp_subject);
  93.         }
  94.         fprintf(tfile,"Subject: %s\n",smtp_subject);
  95.         fprintf(tfile,"\n");       /* add empty line as separator */
  96.     }
  97.  
  98.     if (!tty && fpin == NULLFILE)
  99.         fpin = stdin;
  100.  
  101.     if (fpin != NULLFILE ) {
  102.         while((c = getc(fpin)) != EOF)
  103.             if(putc(c,tfile) == EOF)
  104.                 break;
  105.         if (ferror(tfile)) {
  106.             perror("tmp file");
  107.             (void) fclose(tfile);
  108.             return 1;
  109.         }
  110.     } else {
  111.         /* sending a message not from a file */
  112.         /* copy text from console to the file */
  113.         printf("\nType message text.  Enter a '.' or ctrl/D in column one to end.");
  114.         printf("\nCommands: ~p - redisplay msg, ~e - invoke editor, ~? - help\n\n");
  115.         for(;;) {
  116.             /* read line from console  ie stdin */
  117.             if (gets(tstring) == NULLCHAR)
  118.                 break;
  119.             rip(tstring);
  120.             if(strcmp(tstring,".") == 0 || tstring[0] == '\004')
  121.                 break;
  122.             if (*tstring == '~' ) {
  123.                 switch(tstring[1]) {
  124.                 case 'p':
  125.                     /* Print the message so far */
  126.                     fseek(tfile,0L,0);
  127.                     while (fgets(tstring,sizeof(tstring),tfile) != NULLCHAR)
  128.                         fputs(tstring,stdout);
  129.                     break;
  130.                 case 'e':
  131.                     /* Drop into editor */
  132.                     (void) fclose(tfile);
  133.                     if (editor == NULLCHAR) {
  134.                         printf("No editor defined\n");
  135.                         break;
  136.                     }
  137.                     sprintf(tstring,"%s %s",editor,tf);
  138.                     /* call editor to enter message text */
  139.                     if (system(tstring))
  140.                         printf("unable to invoke editor\n");
  141.                     tfile = fopen(tf,"a+");
  142.                     break;
  143.                 case 'q':
  144.                     (void) fclose(tfile);
  145.                     (void) unlink(tf);
  146.                     printf("Abort\n");
  147.                     return 0;
  148.                 case 'r': 
  149.                     {
  150.                         FILE  *infl;
  151.                         p = &tstring[2];
  152.                         while(*p == ' ' || *p == '\t')
  153.                             p++;
  154.                         if (*p == '\0')
  155.                             printf("No file name specified\n");
  156.                         else
  157.                             if((infl = fopen(p,"r")) == NULLFILE)
  158.                                 printf("No such file\n");
  159.                             else {
  160.                                 printf("Reading file %s\n",p);
  161.                                 while((c = getc(infl)) != EOF)
  162.                                     if(putc(c,tfile) == EOF)
  163.                                         break;
  164.                                 if (ferror(tfile)) {
  165.                                     perror("tmp file");
  166.                                     (void) fclose(tfile);
  167.                                     return 1;
  168.                                 }
  169.                                 (void) fclose(infl);
  170.                             }
  171.  
  172.                         break;
  173.                     }
  174.                 case 'm': 
  175.                     {
  176.                         int    msg;
  177.                         p = &tstring[2];
  178.                         while(*p == ' ' || *p == '\t')
  179.                             p++;
  180.                         if (*p == '\0')
  181.                             msg = current;
  182.                         else
  183.                             msg = atoi(p);
  184.                         if (mfile == NULLFILE || msg < 1 || msg > nmsgs)
  185.                             printf("no such message\n");
  186.                         else {
  187.                             printf("Inserting message %d\n",msg);
  188.                             msgtofile(msg,tfile,0);
  189.                         }
  190.                         break;
  191.                     }
  192.                 case '~':
  193.                     fprintf(tfile,"%s\n",&tstring[1]);
  194.                     break;
  195.                 case '?':
  196.                     printf("~e - Invoke Editor\n");
  197.                     printf("~p - Display message buffer\n");
  198.                     printf("~q - Abort this message\n");
  199.                     printf("~r file - Read file into buffer\n");
  200.                     printf("~m msg - message into buffer\n");
  201.                     printf("~~ - Enter a ~ into message\n");
  202.                     break;
  203.                 default:
  204.                     printf("Unknown ~ escape. ~? for help\n");
  205.                 }
  206.                 printf("(continue)\n");
  207.             } else
  208.                 fprintf(tfile,"%s\n",tstring);
  209.         }
  210.         printf("EOF\n");
  211.  
  212.     }
  213.     queuejob(tfile,tolist);
  214.     recordmsg(tfile,tolist->user);     /* save copy for sender */
  215.     (void) fclose(tfile);
  216.     del_addrlist(tolist);
  217.     (void) unlink(tf);
  218.     return 0;
  219. }
  220.  
  221. /* forward a message in its orginal form */
  222. bouncemsg(mfp,toargs,nargs)
  223. FILE *mfp;
  224. char *toargs[];
  225. int nargs;
  226. {
  227.     struct    addr *list;
  228.     if (nargs == 0) {
  229.         printf("No recpients\n");
  230.     } else if ((list = make_tolist(nargs,toargs)) == NULLADDR) {
  231.         printf("Bad to list\n");
  232.     } else {
  233.         queuejob(mfp,list);
  234.         del_addrlist(list);
  235.     }
  236.     return 0;
  237. }
  238.  
  239. /* Return Date/Time in Arpanet format in passed string */
  240. /* Print out the time and date field as
  241.  *        "DAY day MONTH year hh:mm:ss ZONE"
  242.  */
  243. char *
  244. ptime(t)
  245. long *t;
  246. {
  247.     register struct tm *ltm;
  248.     struct tm *localtime();
  249.     static char tz[4];
  250.     static char str[40];
  251.     extern char *getenv();
  252.     char *p;
  253.     static char *days[7] = {
  254.     "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
  255.  
  256.     static char *months[12] = {
  257.         "Jan","Feb","Mar","Apr","May","Jun",
  258.         "Jul","Aug","Sep","Oct","Nov","Dec" };
  259.  
  260.     /* Read the system time */
  261.     ltm = localtime(t);
  262.  
  263.     if (*tz == '\0')
  264.         if ((p = getenv("TZ")) == NULL)
  265.             strcpy(tz,"GMT");
  266.         else
  267.             strncpy(tz,p,3);
  268.  
  269.     /* rfc 822 format */
  270.     sprintf(str,"%s, %.2d %s %02d %02d:%02d:%02d %.3s\n",
  271.         days[ltm->tm_wday],
  272.         ltm->tm_mday,
  273.         months[ltm->tm_mon],
  274.         ltm->tm_year,
  275.         ltm->tm_hour,
  276.         ltm->tm_min,
  277.         ltm->tm_sec,
  278.         tz);
  279.     return(str);
  280. }
  281.  
  282. /* save copy in the record file */
  283. recordmsg(dfile,to) 
  284. FILE *dfile;
  285. char *to;
  286. {
  287.     register int c;
  288.     FILE     *fp;
  289.     time_t    t;
  290.  
  291.     if (record == NULLCHAR)
  292.         return 1;
  293.     fseek(dfile,0L,0);
  294.     if ((fp = fopen(record,"a")) == NULLFILE) {
  295.         printf("Unable to append to %s\n",record);
  296.     } else {
  297.         (void) time(&t);
  298.         fprintf(fp,"From %s %s",to,ctime(&t));
  299.         while((c = getc(dfile)) != EOF)
  300.             if(putc(c,fp) == EOF)
  301.                 break;
  302.         if (ferror(fp)) {
  303.             (void) fclose(fp);
  304.             return 1;
  305.         }
  306.         (void) fclose(fp);
  307.     }
  308.     return 0;
  309. }
  310.  
  311. /* place a mail job in the outbound queue */
  312. int
  313. queuejob(dfile,tolist)
  314. FILE *dfile;
  315. struct addr *tolist;
  316. {
  317.     FILE *fp;
  318.     char tmpstring[50];
  319.     register struct addr *tp,*sp;
  320.     char prefix[9];
  321.     int c;
  322.     long id;
  323.  
  324.     for (tp = tolist; tp != NULLADDR; tp = tp->next) {
  325.         if (tp->sent)
  326.             continue;
  327.         fseek(dfile,0L,0);
  328.         id = get_msgid();
  329.         sprintf(prefix,"%ld",id);
  330.         (void) mlock(mqueue,prefix);
  331.         sprintf(tmpstring,"%s/%s.txt",mqueue,prefix);
  332.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  333.             printf("unable to open %s\n",tmpstring);
  334.             (void) rmlock(mqueue,prefix);
  335.             return 1;
  336.         }
  337.         while((c = getc(dfile)) != EOF)
  338.             if(putc(c,fp) == EOF)
  339.                 break;
  340.         if (ferror(fp)) {
  341.             (void) fclose(fp);
  342.             (void) rmlock(mqueue,prefix);
  343.             return 1;
  344.         }
  345.         (void) fclose(fp);
  346.         sprintf(tmpstring,"%s/%s.wrk",mqueue,prefix);
  347.         if((fp = fopen(tmpstring,"w")) == NULLFILE) {
  348.             (void) rmlock(mqueue,prefix);
  349.             return 1;
  350.         }
  351.         fprintf(fp,"%s\n%s@%s\n",tp->host,username,hostname);
  352.         fprintf(fp,"%s@%s\n",tp->user,tp->host);
  353.         tp->sent++;
  354.         /* find and other addresses to the same host */
  355.         for (sp = tp->next; sp != NULLADDR; sp = sp->next) {
  356.             if (sp->sent)
  357.                 continue;
  358.             if (strcmp(tp->host,sp->host) == 0) {
  359.                 fprintf(fp,"%s@%s\n",sp->user,sp->host);
  360.                 sp->sent++;
  361.             }
  362.         }
  363.         (void) fclose(fp);
  364.         (void) rmlock(mqueue,prefix);
  365.     }
  366.     return 0;
  367. }
  368.  
  369. #define SKIPWORD(X) while(*X && *X!=' ' && *X!='\t' && *X!='\n' && *X!= ',') X++;
  370. #define SKIPSPACE(X) while(*X ==' ' || *X =='\t' || *X =='\n' || *X == ',') X++;
  371.  
  372. /* check for and alias and expand alais into a address list */
  373. struct addr *
  374. expandalias(head, user)
  375. struct addr **head;
  376. char *user;
  377. {
  378.     FILE *fp;
  379.     register char *s,*p,*h;
  380.     int inalias;
  381.     struct addr *tp;
  382.     char buf[LINELEN];
  383.     
  384.     fp = fopen(alias, "r");
  385.     
  386.         /* no alias file found */
  387.     if (fp == NULLFILE)
  388.         return addrecip(head, user, hostname);
  389.  
  390.     inalias = 0;
  391.     while (fgets(buf,LINELEN,fp) != NULLCHAR) {
  392.         p = buf;
  393.         if ( *p == '#' || *p == '\0')
  394.             continue;
  395.         rip(p);
  396.  
  397.         /* if not in an matching entry skip continuation lines */
  398.         if (!inalias && isspace(*p))
  399.             continue;
  400.  
  401.         /* when processing an active alias check for a continuation */
  402.         if (inalias) {
  403.             if (!isspace(*p)) 
  404.                 break;    /* done */
  405.         } else {
  406.             s = p;
  407.             SKIPWORD(p);
  408.             *p++ = '\0';    /* end the alias name */
  409.             if (strcmp(s,user) != 0)
  410.                 continue;    /* no match go on */
  411.             inalias = 1;
  412.         }
  413.  
  414.         /* process the recipients on the alias line */
  415.         SKIPSPACE(p);
  416.         while(*p != '\0' && *p != '#') {
  417.             s = p;
  418.             SKIPWORD(p);
  419.             if (*p != '\0')
  420.                 *p++ = '\0';
  421.             /* find hostname */
  422.             if ((h = strchr(s,'@')) != NULLCHAR)
  423.                 *h++ = '\0';
  424.             else
  425.                 h = hostname;
  426.             tp = addrecip(head,s,h);
  427.             SKIPSPACE(p);
  428.         }
  429.     }
  430.     (void) fclose(fp);
  431.  
  432.     if (inalias)    /* found and processed and alias. */
  433.         return tp;
  434.  
  435.     /* no alias found treat as a local address */
  436.     return addrecip(head, user, hostname);
  437. }
  438.  
  439. /* convert a arg list to an list of address structures */
  440. struct addr *
  441. make_tolist(argc,argv)
  442. int argc;
  443. char *argv[];
  444. {
  445.     struct addr *tolist, *tp;
  446.     char *user, *host;
  447.     int i;
  448.     tolist = NULLADDR;
  449.     for (i = 0; i < argc; i++) {
  450.         user = argv[i];
  451.         if ((host = strchr(user ,'@')) != NULLCHAR) {
  452.             *host++ = '\0';
  453.             /* if it matches our host name */
  454.             if (stricmp(host,hostname) == 0)
  455.                 host = NULLCHAR;
  456.         }
  457.  
  458.         if (host == NULLCHAR)    /* a local address */
  459.             tp = expandalias(&tolist,user);
  460.         else        /* a remote address */
  461.             tp = addrecip(&tolist, user, host);
  462.  
  463.         if (tp == NULLADDR) {
  464.             printf("Out of memory\n");
  465.             del_addrlist(tolist);
  466.             return NULLADDR;
  467.         }
  468.     }
  469.     return tolist;
  470. }
  471.  
  472. /* delete a list of mail addresses */
  473. del_addrlist(list)
  474. struct addr *list;
  475. {
  476.     struct addr *tp, *tp1;;
  477.     for (tp = list; tp != NULLADDR; tp = tp1) {
  478.         tp1 = tp->next;
  479.         if (tp->user != NULLCHAR);
  480.             free(tp->user);
  481.         if (tp->host != NULLCHAR);
  482.             free(tp->host);
  483.         (void) free((char *)tp);
  484.     }
  485. }
  486.  
  487. /* add an address to the from of the list pointed to by head 
  488. ** return NULLADDR if out of memory.
  489. */
  490. struct addr *
  491. addrecip(head,user,host)
  492. struct addr **head;
  493. char *user, *host;
  494. {
  495.     register struct addr *tp;
  496.  
  497.     tp = (struct addr *)calloc(1,sizeof(struct addr));
  498.     if (tp == NULLADDR)
  499.         return NULLADDR;
  500.  
  501.     tp->next = NULLADDR;
  502.  
  503.     /* allocate storage for the user's login */
  504.     if ((tp->user = malloc((unsigned)strlen(user)+1)) == NULLCHAR) {
  505.         (void) free((char *)tp);
  506.         return NULLADDR;
  507.     }
  508.     strcpy(tp->user,user);
  509.  
  510.     /* allocate storage for the host name */
  511.     if (host != NULLCHAR)
  512.         if ((tp->host = malloc((unsigned)strlen(host)+1)) == NULLCHAR) {
  513.             (void) free(tp->user);
  514.             (void) free((char *)tp);
  515.             return NULLADDR;
  516.         }
  517.     strcpy(tp->host,host);
  518.  
  519.     /* add entry to front of existing list */
  520.     if (*head == NULLADDR)
  521.         *head = tp;
  522.     else {
  523.         tp->next = *head;
  524.         *head = tp;
  525.     }
  526.     return tp;
  527.  
  528. }
  529.